#!/bin/bash

MAXINDEX="--max-index -1"
TRANSPORT="--transport zeromq"
VERBOSE="--severity INFO"
FAIRTASKNAME="--task-name PixelFindHits"
NOFPROCESSORS=3

WORKDIR="@EXAMPLE9_FILE_LOCATION@"

FORCEKILL=false
COMMAND="interactive"
MAXRUNNINGTIME=100
DATESTRING=`date +%Y%m%d_%H%M%S`

while [[ $# > 1 ]]
do
key="$1"

case $key in
    -f|--task-name)
    FAIRTASKNAME="--task-name $2"
    shift
    ;;
    -m|--max-index)
    MAXINDEX="--max-index $2"
    shift
    ;;
    -t|--transport)
    TRANSPORT="--transport $2"
    shift
    ;;
    -p|--nof-processors)
    NOFPROCESSORS="$2"
    shift
    ;;
    -c|--command)
    COMMAND="$2"
    shift
    ;;
    -m|--max-running-time)
    MAXRUNNINGTIME="$2"
    shift
    ;;
    -w|--work-dir)
    WORKDIR="$2"
    shift
    ;;
    -k|--force-kill)
    FORCEKILL="$2"
    shift
    ;;
    -v|--verbose)
    VERBOSE="--severity $2"
    shift
    ;;
esac
shift 
done

CONTROL=""
if [ "$COMMAND" == "static" ]; then
    CONTROL="--control static --log-color false"
fi

########################### Define some variables
# ASCII and ROOT parameter files for the processor device
ROOTPARAM="$WORKDIR/examples/MQ/pixelDetector/macros/pixel_TGeant3.params.root"
ASCIIPARAM="$WORKDIR/examples/MQ/pixelDetector/param/pixel_digi.par"

if [ "$FAIRTASKNAME" == "--task-name PixelFindHits" ] ; then
    # input file and branch for the sampler device
    INPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/pixel_TGeant3.digi.root"
 #   INPUTFILE+=" --file-name $WORKDIR/examples/MQ/pixelDetector/macros/pixel_TGeant3.digi.f1.root"
    INPUTBRANCH="PixelDigis"
    
    # output file for sink
    OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.pixel_TGeant3.hits.root"
    OUTPUTCLASS="--class-name TClonesArray(PixelHit)"
    OUTPUTBRANCH="--branch-name PixelHits"
elif [ "$FAIRTASKNAME" == "--task-name PixelFindTracks" ] ; then
    # input file and branch for the sampler device 
    FAIRTASKNAME+=" --keep-data PixelHits"
    INPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.pixel_TGeant3.hits.root"
    INPUTBRANCH="PixelHits"
    
    # output file for sink
    OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.pixel_TGeant3.hits_tracks.root"
    OUTPUTCLASS="--class-name TClonesArray(PixelHit) --class-name TClonesArray(PixelTrack)"
    OUTPUTBRANCH="--branch-name PixelHits --branch-name PixelTracks"
elif [ "$FAIRTASKNAME" == "--task-name PixelFitTracks" ] ; then
    # input file and branch for the sampler device
    INPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.pixel_TGeant3.hits_tracks.root"
    INPUTBRANCH="PixelHits --branch-name PixelTracks"
    
    # output file for sink
    OUTPUTFILE="$WORKDIR/examples/MQ/pixelDetector/macros/MQ.pixel_TGeant3.fitTracks.root"
    OUTPUTCLASS="--class-name TClonesArray(PixelTrack)"
    OUTPUTBRANCH="--branch-name PixelFitTracks"
else
    echo "TASK $FAIRTASKNAME UNKNOWN!!!"
    exit
fi
###########################



########################### Start the chain of the devices


########################## start Parameter server
SERVER="@FAIRROOT_BIN_LOCATION@/"
SERVER+="parmq-server $TRANSPORT"
SERVER+=" --id pixDet-parmq-server --channel-config name=param,type=rep,method=bind,rateLogging=0,address=tcp://*:5105"
SERVER+=" --channel-name param --first-input-name $ROOTPARAM --second-input-name $ASCIIPARAM --second-input-type ASCII $CONTROL"

########################## start SAMPLER
SAMPLER="@PIXEL_BIN_LOCATION@/"
SAMPLER+="pixel-sampler $TRANSPORT"
SAMPLER+=" --id pixDet-sampler1 --severity info"
SAMPLER+=" --channel-config name=data-out,type=push,method=bind,rateLogging=1,address=tcp://*:5106"
if [ "$COMMAND" == "static" ]; then
    SAMPLER+=" --ack-channel ack --channel-config name=ack,type=pull,method=bind,rateLogging=0,address=tcp://*:5108"
fi
SAMPLER+=" --file-name $INPUTFILE --branch-name $INPUTBRANCH --branch-name EventHeader. $MAXINDEX $CONTROL"

########################## start PROCESSORs
PROCESSOR="@PIXEL_BIN_LOCATION@/"
PROCESSOR+="pixel-processor $TRANSPORT"
PROCESSOR+=" $VERBOSE"
PROCESSOR+=" --channel-config name=param,type=req,method=connect,rateLogging=0,address=tcp://localhost:5105"
PROCESSOR+=" --channel-config name=data-in,type=pull,method=connect,rateLogging=1,address=tcp://localhost:5106"
PROCESSOR+=" --channel-config name=data-out,type=push,method=connect,rateLogging=1,address=tcp://localhost:5107"
PROCESSOR+=" $FAIRTASKNAME $CONTROL"

for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
do
    APROCESSOR[i]="$PROCESSOR --id pixDet-processor$((i+1))"
done

########################## start FILESINK
FILESINK="@PIXEL_BIN_LOCATION@/"
FILESINK+="pixel-sink $TRANSPORT"
FILESINK+=" --id pixDet-sink1 --channel-config name=data-in,type=pull,method=bind,rateLogging=1,address=tcp://*:5107"
if [ "$COMMAND" == "static" ]; then
    FILESINK+=" --ack-channel ack --channel-config name=ack,type=push,method=connect,rateLogging=0,address=tcp://localhost:5108"
fi
FILESINK+=" --file-name $OUTPUTFILE --class-name FairEventHeader --branch-name EventHeader. $OUTPUTCLASS $OUTPUTBRANCH $CONTROL"

########################## run all
if [ "$COMMAND" == "print" ]; then
    echo $SERVER
    echo $SAMPLER

    echo "THERE ARE $NOFPROCESSORS PROCESSORS."
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        echo ${APROCESSOR[i]}
    done

    echo $FILESINK
fi

if [ "$COMMAND" == "interactive" ]; then
    xterm -geometry 80x25+0+350 -hold -e $SERVER &
    xterm -geometry 80x25+0+0 -hold -e $SAMPLER &
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        xterm -geometry 80x50+500+0 -hold -e ${APROCESSOR[i]} &
    done
    xterm +aw -geometry 100x25+0+700 -hold -e $FILESINK &
fi


if [ "$COMMAND" == "static" ]; then

    CHECK_BEFORE="$(ps -fea | grep pixDet | grep -v grep)"
    if [ -n "$CHECK_BEFORE" ];
    then
        echo "some example/MQ/pixel programs are still running:"
        echo $CHECK_BEFORE
        echo "quit them before proceeding."
        if [ "$FORCEKILL" == "true" ];
        then
            echo "trying to kill..."
            ps -fea | grep pixDet | grep -v grep | awk '{print $2}' | xargs kill -9
        else
            exit
        fi
    fi

    $SERVER &> server_$DATESTRING.out.log &
    SERVER_PID=$!

    $SAMPLER &> sampler_$DATESTRING.out.log &
    SAMPLER_PID=$!

    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        ${APROCESSOR[i]} &> processor${i}_$DATESTRING.out.log &
        APROCESSOR_PID[i]=$!
    done

    $FILESINK &> fileSink_$DATESTRING.out.log &
    FILESINK_PID=$!

    RUN_STRING="Running"

    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "_______________"
    done
    printf "_\n|    server    |"
    printf "    sampler   |"
    for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
    do
        printf "   processor  |"
    done
    printf "   file sink  |\n| pid = %6d | pid = %6d |" $SERVER_PID $SAMPLER_PID
    for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
    do
        printf " pid = %6d |" ${APROCESSOR_PID[iproc]}
    done
    printf " pid = %6d |\n" $FILESINK_PID
    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "|   CPU    mem ";
    done
    printf "|\n"

    SAMPLERRUNNING=0
    for ((isec = 0 ; isec < MAXRUNNINGTIME ; isec++ ));
    do
        CHECK_SAMPLER="$(kill -0 $SAMPLER_PID &> /dev/null && echo $RUN_STRING)";
        if [ "$CHECK_SAMPLER" != "$RUN_STRING" ];
        then
	    break;
        fi

        SERVER_INFO="$(ps -o %cpu -o rss $SERVER_PID | tail -1)"
        SAMPLER_INFO="$(ps -o %cpu -o rss $SAMPLER_PID | tail -1)"
        printf   "| %5s %6s | %5s %6s |" $SERVER_INFO $SAMPLER_INFO
        for (( iproc=0 ; iproc<$NOFPROCESSORS ; iproc++ ))
        do
            APROCESSOR_INFO="$(ps -o %cpu -o rss ${APROCESSOR_PID[iproc]} | tail -1)"
            printf " %5s %6s |" $APROCESSOR_INFO;
        done
        FILESINK_INFO="$(ps -o %cpu -o rss $FILESINK_PID | tail -1)"
        printf   " %5s %6s |\r" $FILESINK_INFO
        sleep 1
    done
    for (( iproc=0 ; iproc<$NOFPROCESSORS+3 ; iproc++ ))
    do
        printf "_______________"
    done
    printf "_\n"

    echo "Jobs finished in $isec seconds."

    sleep 2;

    kill $SERVER_PID
    CHECK_SAMPLER="$(kill -0 $SAMPLER_PID &> /dev/null && echo $RUN_STRING)";
    if [ "$CHECK_SAMPLER" == "$RUN_STRING" ];
    then
	kill $SAMPLER_PID;
    fi
    for (( i=0 ; i<$NOFPROCESSORS ; i++ ))
    do
        echo "checking and trying to kill ${APROCESSOR_PID[isimul]}"
        CHECK_APROCESSOR="$(kill -0 ${APROCESSOR_PID[isimul]} &> /dev/null && echo $RUN_STRING)";
        if [ "$CHECK_APROCESSOR" == "$RUN_STRING" ];
        then
            kill ${APROCESSOR_PID[i]};
        fi
    done
    echo "trying to kill $FILESINK_PID"
    kill $FILESINK_PID

    wait $FILESINK_PID

    INPUT_EVENTS="$(echo "cout<<cbmsim->GetEntries()<<endl;" | root -l -b $INPUTFILE | tail -1)"
    OUTPUT_EVENTS="$(echo "cout<<cbmsim->GetEntries()<<endl;" | root -l -b $OUTPUTFILE | tail -1)"
    echo "There are $INPUT_EVENTS events in the input file."
    echo "There are $OUTPUT_EVENTS events in the output file."

    if [ "$OUTPUT_EVENTS" -eq "$INPUT_EVENTS" ];
    then
        echo "Shell script finished successfully.";
    fi
fi
